package com.xyj.data.data_controller_demo.dataFilter.core;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xyj.data.data_controller_demo.dataFilter.annotation.DataAllow;
import com.xyj.data.data_controller_demo.dataFilter.modle.FunctionCol;
import com.xyj.data.data_controller_demo.dataFilter.util.FunctionUtil;
import com.xyj.data.data_controller_demo.dataFilter.util.PageDataFilter;
import com.xyj.data.data_controller_demo.dataFilter.util.UrlUtil;
import com.xyj.data.data_controller_demo.domain.DemoFiled;
import com.xyj.data.data_controller_demo.domain.DemoFunction;
import com.xyj.data.data_controller_demo.domain.DemoUser;
import com.xyj.data.data_controller_demo.domain.DemoUserField;
import com.xyj.data.data_controller_demo.service.DemoFiledService;
import com.xyj.data.data_controller_demo.service.DemoFunctionService;
import com.xyj.data.data_controller_demo.service.DemoUserFieldService;
import com.xyj.data.data_controller_demo.util.HeaderUtil;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author xyj
 * @date 2023/12/12
 * <p>
 * 条件管理器
 */
@Slf4j
@Component
public class ConditionManager implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Autowired
    private UrlUtil urlUtil;

    @Autowired
    private FunctionUtil functionUtil;

    @Autowired
    private DemoFunctionService demoFunctionService;

    @Autowired
    private DemoFiledService demoFiledService;
    @Autowired
    private DemoUserFieldService demoUserFieldService;

    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private HeaderUtil headerUtil;


    /**
     * 根据功能ID和用户id或者角色id来获取当前用户功能
     *
     * @param url 功能ID
     */
    public List<DemoUserField> getUserConditionByFunctionId(String url) {
        DemoUser userFromHeader = headerUtil.getUserFromHeader(httpServletRequest);
        if (userFromHeader == null) {
            return null;
        }
        Long userId = userFromHeader.getId();

        DemoFunction one = demoFunctionService.getOne(new LambdaQueryWrapper<DemoFunction>().eq(DemoFunction::getUrl, url));
        Long functionId = one.getId();
        return demoUserFieldService.list(new LambdaQueryWrapper<DemoUserField>().eq(DemoUserField::getUserId, userId)
                .eq(DemoUserField::getFunctionId, functionId));
    }


    @PostConstruct
    public void init() {
        initDataAllow();
    }

    @Transactional
    public void initDataAllow() {
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(Controller.class);
        if (beansWithAnnotation.isEmpty()) {
            log.info("没有找到任何带有@Controller注解的bean");
            return;
        }
        Collection<Object> values = beansWithAnnotation.values();
        values.stream().map(e -> urlUtil.excludeProxyStr(e.getClass().getName())).forEach(className -> {
            Class<?> aClass = null;
            try {
                aClass = Class.forName(className);
            } catch (ClassNotFoundException ex) {
                log.error(ex.getMessage());
                throw new RuntimeException(ex);
            }
            log.info(aClass.getName());
            Method[] methods = aClass.getDeclaredMethods();
            for (Method method : methods) {
                DataAllow annotation = method.getAnnotation(DataAllow.class);
                if (annotation != null) {
                    List<FunctionCol> allowFields = functionUtil.getAllowFields(annotation.value());
                    if (!CollectionUtils.isEmpty(allowFields)) {
                        log.info("方法名称：{},{}, {}", aClass.getName(), method.getName(), annotation != null);
                        String url = urlUtil.getCompleteUrlByMethod(method);
                        log.info("方法路径: {}", url);
                        //todo 存入数据库
                        DemoFunction demoFunction = new DemoFunction();
                        demoFunction.setUrl(url);
                        demoFunction.setDesct(annotation.desc());
                        DemoFunction one = demoFunctionService.getOne(new LambdaQueryWrapper<DemoFunction>().eq(DemoFunction::getUrl, url));
                        if (one == null) {
                            demoFunctionService.save(demoFunction);
                        } else {
                            demoFunction.setId(one.getId());
                            demoFunctionService.updateById(demoFunction);
                        }
                        Long id = demoFunction.getId();
                        ArrayList<Long> longs = new ArrayList<>();
                        for (FunctionCol allowField : allowFields) {
                            DemoFiled demoFiled = new DemoFiled();
                            demoFiled.setFunctionId(id);
                            demoFiled.setType(allowField.getColType());
                            demoFiled.setName(allowField.getColName());
                            demoFiled.setDesct(allowField.getColNameDesc());
                            DemoFiled one1 = demoFiledService.getOne(new LambdaQueryWrapper<DemoFiled>().eq(DemoFiled::getName, allowField.getColName())
                                    .eq(DemoFiled::getType, allowField.getColType())
                                    .eq(DemoFiled::getFunctionId, id));
                            if (one1 == null) {
                                demoFiledService.save(demoFiled);
                            } else {
                                demoFiled.setId(one1.getId());
                                demoFiledService.updateById(demoFiled);
                            }
                            Long id1 = demoFiled.getId();
                            longs.add(id1);
                        }
                        //删除未处理过的field
                        demoFiledService.remove(new LambdaQueryWrapper<DemoFiled>().eq(DemoFiled::getFunctionId, id).notIn(DemoFiled::getId, longs));

                    }

                }
            }
        });
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }


    public static void main(String[] args) {
      /*  UrlUtil urlUtil = new UrlUtil();
        Method[] declaredMethods = BaseAreaController.class.getDeclaredMethods();
        for (int i = 0; i < declaredMethods.length; i++) {
            String name = declaredMethods[i].getName();

            DataAllow annotation = declaredMethods[i].getAnnotation(DataAllow.class);
            if (annotation != null) {
                System.out.println(name);
            }
        }
        System.out.println(BaseAreaController.class.getName());
        String test = "org.panda.back.controller.OssController$$SpringCGLIB$$0";
        String s = urlUtil.excludeProxyStr(test);
        System.out.println(s);*/
        String name = PageDataFilter.class.getName();
        System.out.println(name);
    }

}
